package com.hup.utils.io.audio;

import lombok.Getter;

import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;

/**
 * 音频文件信息;本类属性的无深入学习,概念上可能有误!
 * <pre>
 * 音频中的采样率和比特率的关系:
 *  https://blog.csdn.net/qq_38907791/article/details/88925224
 * </pre>
 *
 * @author hugan
 * @date 2020/5/28
 */
@Getter
public class AudioInfo {

    private final String resourcePath;
    private final String fileName;
    private final AudioFormat audioFormat;

    /**
     * 每秒播放帧数/采样率:Hz
     */
    private float sampleRate;
    /**
     * 时长:秒
     */
    private float timeSpan;
    /**
     * 比特率:kbps
     */
    private final int bitRate;

    public AudioInfo(String resourcePath) {
        this(resourcePath, null);
    }

    /**
     * @param resourcePath jar内,resources下的文件路径,如["/audio/xxx.xx"]
     * @param lineCreator 用于AudioSystem.getLine
     * @apiNote 支持的文件格式:wav,au???
     */
    public AudioInfo(String resourcePath, LineCreator lineCreator) {
        URL url = getClass().getResource(resourcePath);
        if (url == null) throw new IllegalArgumentException("找不到:" + resourcePath);

        this.resourcePath = resourcePath;
        fileName = new File(resourcePath).getName();
        try (AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url)) {
            audioFormat = audioInputStream.getFormat();
            sampleRate = audioFormat.getSampleRate();
            //时长=总帧数/采样率
            timeSpan = audioInputStream.getFrameLength() / sampleRate;

            //分辨率(名字引自AU):8/16/32位
            int sampleSizeInBits = audioFormat.getSampleSizeInBits();
            int channels = audioFormat.getChannels();//通道:1-单声道,2-立体声
            bitRate = (int) (sampleRate * (sampleSizeInBits * channels) / 1000);//比特率=采样率*(分辨率*声道数)
            if (lineCreator != null) {
                lineCreator.create(audioInputStream);
            }
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
            throw new RuntimeException("[" + fileName + "]解析异常", e);
        }
    }

    @Override
    public String toString() {
        return "AudioInfo{" +
                "fileName='" + fileName + '\'' +
                ", sampleRate=" + sampleRate + "Hz" +
                ", timeSpan=" + timeSpan + "s" +
                ", bitRate=" + bitRate + "kbps" +
                '}';
    }

    /**
     * 用于AudioSystem.getLine
     */
    public interface LineCreator {
        void create(AudioInputStream audioInputStream)
                throws IOException, UnsupportedAudioFileException, LineUnavailableException;
    }

}
